package edu.pitt.cs.zhangfan.sa.core;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;

import edu.pitt.cs.zhangfan.sa.io.ExcelReader;
import edu.pitt.cs.zhangfan.sa.model.Document;
import edu.pitt.cs.zhangfan.sa.model.DocumentPair;

public class SequenceGenerator {
	public void align(String path, String path2, int option,
			String resultPath) throws IOException {
		ExcelReader reader = new ExcelReader();
		ArrayList<DocumentPair> testDps = new ArrayList<DocumentPair>();
		File folder2 = new File(path2);
		File[] subs2 = folder2.listFiles();
		for (int i = 0; i < subs2.length; i++) {
			DocumentPair dp = reader.readDocs(subs2[i].getAbsolutePath());
			//docPairs.add(dp);
			testDps.add(dp);
		}
		// Start Aligning
				ArrayList<ArrayList<String>> sequences = alignOnSequenceDP(testDps);
				for (int i = 0; i < sequences.size(); i++) {
					String fileName = resultPath + "/" + i + ".txt";
					writeSequence2(fileName, sequences.get(i));
				}
	}
	
	public void writeSequence2(String fileName, ArrayList<String> sequence)
			throws IOException {
		BufferedWriter writer = new BufferedWriter(new FileWriter(fileName));
		int len = sequence.size();
		for (int i = 0; i < len; i++) {
			writer.append(sequence.get(i) + "\n");
		}
		writer.close();
	}

	
	public void writeSequence(String fileName, ArrayList<String> sequence)
			throws IOException {
		BufferedWriter writer = new BufferedWriter(new FileWriter(fileName));
		int len = sequence.size() - 1;
		for (int i = len; i >= 0; i--) {
			writer.append(sequence.get(i) + "\n");
		}
		writer.close();
	}
	
	public ArrayList<ArrayList<String>> alignOnSequenceDP(
			ArrayList<DocumentPair> dps) {
		ArrayList<ArrayList<String>> editSequences = new ArrayList<ArrayList<String>>();
		for (int i = 0; i < dps.size(); i++) {
			DocumentPair dp = dps.get(i);
			Document srcDoc = dp.getSrc();
			Document destDoc = dp.getModified();
			//srcDoc.getSentences().get(i).getAlignedIndex();
			ArrayList<Integer> srcIndexes = new ArrayList<Integer>();
			for (int j = 0; j < srcDoc.getSentences().size(); j++) {
				srcIndexes.add(j + 1);
			}

			ArrayList<Integer> destIndexes = new ArrayList<Integer>();
			for (int j = 0; j < destDoc.getSentences().size(); j++) {
				if(destDoc.getSentences().get(j).getAlignedIndex().size()>0) {
					destIndexes.add(destDoc.getSentences().get(j).getAlignedIndex()
						.get(0));
				} else {
					destIndexes.add(-1);
				}
			}

			int addcost = 1;
			int deletecost = 1;
			int modcost = 1;

			int srcSize = srcIndexes.size();
			int destSize = destIndexes.size();

			int[][] dpCost = new int[srcSize][destSize];
			String[][] oper = new String[srcSize][destSize];
			for (int m = 0; m < srcSize; m++) {
				for (int n = 0; n < destSize; n++) {
					if (m == 0 || n == 0) {
						dpCost[m][n] = (m+n)*addcost;
						oper[m][n] = "ADD";
					} else {
						int add = dpCost[m][n - 1] + addcost;
						int delete = dpCost[m - 1][n] + deletecost;
						int modify = dpCost[m - 1][n - 1] + modcost;
						int nochange = Integer.MAX_VALUE;
						if (srcIndexes.get(m) == destIndexes.get(n)) {
							nochange = dpCost[m - 1][n - 1];
						}

						int smallest = Integer.MAX_VALUE;
						if (add < smallest)
							smallest = add;
						if (delete < smallest)
							smallest = delete;
						if (modify < smallest)
							smallest = modify;
						if (nochange < smallest)
							smallest = nochange;

						if (add == smallest) {
							oper[m][n] = "ADD";
						} else if (delete == smallest) {
							oper[m][n] = "DELETE";
						} else if (modify == smallest) {
							oper[m][n] = "MODIFY";
						} else if (modify == nochange) {
							oper[m][n] = "KEEP";
						}
						dpCost[m][n] = smallest;
					}
				}
			}
			
			ArrayList<String> editSequence = new ArrayList<String>();
			int m = srcSize - 1;
			int n = destSize - 1;
			while(m>=1 || n>=1) {
				if(dpCost[m][n] == dpCost[m][n-1] + addcost) {
					editSequence.add("ADD");
					n--;
				} else if(dpCost[m][n] == dpCost[m-1][n] + deletecost) {
					editSequence.add("DELETE");
					m--;
				} else if(dpCost[m][n] == dpCost[m-1][n-1] + modcost) {
					editSequence.add("REPLACE");
					m--;
					n--;
				} else {
					editSequence.add("KEEP");
					m--;
					n--;
				}
			}
			ArrayList<String> editSequenceRev = new ArrayList<String>();
			for(int l = editSequence.size()-1;l>=0;l--) {
				editSequenceRev.add(editSequence.get(l));
			}
			editSequences.add(editSequenceRev);
		}
		return editSequences;
	}
}
